(*
  Copyright (c) 2009 Barry Schwartz

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*)

(*-----------------------------------------------------------------------*)
(* Interface to the kpathsea library. *)

type file_type =
  [
  | `PK | `Source | `TeX | `TFM | `AFM | `Type1 | `TrueType | `OpenType
  ]

let kpse_gf_format = 0
let kpse_pk_format = 1
let kpse_any_glyph_format = 2           (* ``any'' meaning gf or pk *)
let kpse_tfm_format = 3
let kpse_afm_format = 4
let kpse_base_format = 5
let kpse_bib_format = 6
let kpse_bst_format = 7
let kpse_cnf_format = 8
let kpse_db_format = 9
let kpse_fmt_format = 10
let kpse_fontmap_format = 11
let kpse_mem_format = 12
let kpse_mf_format = 13
let kpse_mfpool_format = 14
let kpse_mft_format = 15
let kpse_mp_format = 16
let kpse_mppool_format = 17
let kpse_mpsupport_format = 18
let kpse_ocp_format = 19
let kpse_ofm_format = 20
let kpse_opl_format = 21
let kpse_otp_format = 22
let kpse_ovf_format = 23
let kpse_ovp_format = 24
let kpse_pict_format = 25
let kpse_tex_format = 26
let kpse_texdoc_format = 27
let kpse_texpool_format = 28
let kpse_texsource_format = 29
let kpse_tex_ps_header_format = 30
let kpse_troff_font_format = 31
let kpse_type1_format = 32
let kpse_vf_format = 33
let kpse_dvips_config_format = 34
let kpse_ist_format = 35
let kpse_truetype_format = 36
let kpse_type42_format = 37
let kpse_web2c_format = 38
let kpse_program_text_format = 39
let kpse_program_binary_format = 40
let kpse_miscfonts_format = 41
let kpse_web_format = 42
let kpse_cweb_format = 43
let kpse_enc_format = 44
let kpse_cmap_format = 45
let kpse_sfd_format = 46
let kpse_opentype_format = 47
let kpse_pdftex_config_format = 48
let kpse_lig_format = 49
let kpse_texmfscripts_format = 50
let kpse_lua_format = 51
let kpse_last_format = 52               (* one past last index *)

(* Non-standard formats *)
let kpse_ant_format = 200

external kpse_init_prog : string -> int -> string -> string -> unit = "kpse_init_prog_wrapper"
external kpse_set_program_name : string -> string -> unit = "kpse_set_program_name_wrapper"
external kpse_set_program_enabled : int -> int -> int -> unit = "kpse_set_program_enabled_wrapper"
external kpse_find_file : string -> int -> bool -> string = "kpse_find_file_wrapper"
external kpse_find_glyph : string -> int -> int -> string = "kpse_find_glyph_wrapper"
external kpse_var_value : string -> string = "kpse_var_value_wrapper"
external kpse_var_expand : string -> string = "kpse_var_expand_wrapper"
external kpse_expand : string -> string = "kpse_expand_wrapper"
external kpse_brace_expand : string -> string = "kpse_brace_expand_wrapper"
external kpse_path_expand : string -> string = "kpse_path_expand_wrapper"
external kpse_path_search : string -> string -> bool -> string = "kpse_path_search_wrapper"

let antinputs_path = ref None

let find_resource ?(format = kpse_ant_format) ?(must_exist = true) resource_name =
  let resource =
    if format = kpse_ant_format then
      let inputs_path =
        match !antinputs_path with
          | None ->
              let p = kpse_path_expand "$ANTINPUTS" in
                antinputs_path := Some p;
                p
          | Some p -> p
      in
        kpse_path_search inputs_path resource_name must_exist
    else
      kpse_find_file resource_name format must_exist
  in
    if resource = "" then
      raise Not_found;
    resource
  
let find_file name file_type must_exist =
  match file_type with
    | `PK -> kpse_find_file name kpse_pk_format must_exist
    | `TFM -> kpse_find_file name kpse_tfm_format must_exist
    | `AFM -> kpse_find_file name kpse_afm_format must_exist
    | `TeX -> kpse_find_file name kpse_tex_format must_exist
    | `Type1 -> kpse_find_file name kpse_type1_format must_exist
    | `TrueType -> kpse_find_file name kpse_truetype_format must_exist
    | `OpenType -> kpse_find_file name kpse_opentype_format must_exist
    | _ -> name
  
let find_glyph name dpi = kpse_find_glyph name dpi kpse_pk_format

(*-----------------------------------------------------------------------*)

open Pycaml
open Python_tools

let py_kpse_init_prog =
  python_interfaced_function
    [| EitherStringType; IntType; EitherStringType; EitherStringType |]
    begin
      fun py_args ->
          let name = unpythonize_string py_args.(0) in
          let dpi = pyint_asint py_args.(1) in
          let mode = unpythonize_string py_args.(2) in
          let alt_font = unpythonize_string py_args.(3) in
            kpse_init_prog name dpi mode alt_font;
            pynone ()
    end

let py_kpse_set_program_name =
  python_interfaced_function
    [| EitherStringType; EitherStringType |]
    begin
      fun py_args ->
        let argv0 = unpythonize_string py_args.(0) in
        let progname = unpythonize_string py_args.(1) in
          kpse_set_program_name argv0 progname;
          pynone ()
    end

let py_kpse_set_program_enabled =
  python_interfaced_function
    [| IntType; IntType; IntType |]
    begin
      fun py_args ->
        let format = pyint_asint py_args.(0) in
        let value = pyint_asint py_args.(1) in
        let level = pyint_asint py_args.(2) in
          kpse_set_program_enabled format value level;
          pynone ()
    end

let py_kpse_find_file =
  python_interfaced_function
    [| EitherStringType; IntType; BoolType |]
    begin
      fun py_args ->
        let name = unpythonize_string py_args.(0) in
        let format = pyint_asint py_args.(1) in
        let must_exist = unpythonize_bool py_args.(2) in
        let filename = kpse_find_file name format must_exist in
          pythonize_string filename
    end

let py_kpse_find_glyph =
  python_interfaced_function
    [| EitherStringType; IntType; IntType |]
    begin
      fun py_args ->
        let name = unpythonize_string py_args.(0) in
        let dpi = pyint_asint py_args.(1) in
        let format = pyint_asint py_args.(2) in
        let filename = kpse_find_glyph name dpi format in
          pythonize_string filename
    end

let py_kpse_var_function funct =
  python_interfaced_function
    [| EitherStringType |]
    begin
      fun py_args ->
        let s = unpythonize_string py_args.(0) in
          try pythonize_string (funct s)
          with | Not_found -> pynone ()
    end

let py_kpse_var_value = py_kpse_var_function kpse_var_value
let py_kpse_var_expand = py_kpse_var_function kpse_var_expand

let py_kpse_expansion_function funct =
  python_interfaced_function
    [| EitherStringType |]
    (fun py_args ->
        let s = unpythonize_string py_args.(0) in
          pythonize_string (funct s))

let py_kpse_expand = py_kpse_expansion_function kpse_expand
let py_kpse_brace_expand = py_kpse_expansion_function kpse_brace_expand
let py_kpse_path_expand = py_kpse_expansion_function kpse_path_expand

let py_kpse_path_search =
  python_interfaced_function
    [| EitherStringType; EitherStringType; BoolType |]
    (fun py_args ->
        let path = unpythonize_string py_args.(0) in
        let name = unpythonize_string py_args.(1) in
        let must_exist = py_is_true py_args.(2) in
          try
            pythonize_string (kpse_path_search path name must_exist)
          with
            | Not_found -> pynone ())

let py_find_resource =
  python_interfaced_function
    [| EitherStringType; IntType; BoolType |]
    (fun py_args ->
       let resource_name = unpythonize_string py_args.(0) in
       let format = pyint_asint py_args.(1) in
       let must_exist = py_is_true py_args.(2) in
         try
           pythonize_string (find_resource ~format ~must_exist resource_name)
         with
           | Not_found -> pynone ())

  let _ =
    register_for_python
      [|
        ("kpse_init_prog",           py_kpse_init_prog);
        ("kpse_set_program_name",    py_kpse_set_program_name);
        ("kpse_set_program_enabled", py_kpse_set_program_enabled);
        ("kpse_find_file",           py_kpse_find_file);
        ("kpse_find_glyph",          py_kpse_find_glyph);
        ("kpse_var_value",           py_kpse_var_value);
        ("kpse_var_expand",          py_kpse_var_expand);
        ("kpse_expand",              py_kpse_expand);
        ("kpse_brace_expand",        py_kpse_brace_expand);
        ("kpse_path_expand",         py_kpse_path_expand);
        ("kpse_path_search",         py_kpse_path_search);
        ("find_resource",            py_find_resource);
      |]

(*-----------------------------------------------------------------------*)
